using namespace std;
#include<sys/wait.h>
#include<sys/types.h>
#include<string>
#include<unistd.h>
#include<vector>
#include<iostream>
#include"task.hpp"
class channel
{
    public:
    channel(int fd,pid_t id):_wfd(fd),_subid(id)    
    {
        _name="channel-"+std::to_string(_wfd)+"-"+std::to_string(_subid);
    }
    ~channel()
    {

    }
    void Send(int code)
    {
        int n = write(_wfd,&code,sizeof(code));
    }
    void Close()
    {
        close(_wfd);
    }
    void Wait()
    {
        waitpid(_subid,nullptr,0);
    }
    int Fd(){return _wfd;}
    pid_t Id(){return _subid;}
    std::string Name(){return _name;}
    private:
    int _wfd;
    pid_t _subid;
    std::string _name;
};
class channelmanage
{
    public:
    channelmanage():_next(0)
    {}
    void Insert(int wfd,pid_t wid)
    {
        _channels.emplace_back(channel(wfd,wid));
    }
    channel &Select()
    {
        channel & s=_channels[_next];
        _next++;
        _next=_next%_channels.size();
        return s; 
    }
    void Printchannel()
    {
        for(auto & signalchannel:_channels)
        {
            std::cout<<signalchannel.Name()<<std::endl;
        }
    }
    void Stopchannels()
    {
        for(auto & singalchannel:_channels)
        {
            singalchannel.Close();
            std::cout<<"关闭文件:"<<singalchannel.Name()<<std::endl;
        }
    }
    void Waitchannels()
    {
        for(auto & singalchannel:_channels)
        {
            singalchannel.Wait();
            std::cout<<"关闭进程:"<<singalchannel.Name()<<std::endl;
        }
    }
    ~channelmanage()
    {}
    private:
    std::vector<channel>_channels;
    int _next;
};
class processpool
{
    public:
    processpool(int num):process_num(num)
    {
        tm.Register(upload);
        tm.Register(download);
        tm.Register(printlog);

    }
    void Work(int rfd)
    {
        while(true)
        {
            int code;
            ssize_t n = read(rfd,&code,sizeof(code));
            if(n>0)
            {
                if(n!=sizeof(code))
                {
                    continue;
                }
                cout<<"子进程["<<getpid()<<"]收到任务码:"<<code<<endl;
                tm.Execute(code);
            }
            else if(n==0)
            {
                cout<<"子进程退出"<<endl;
                break;
            }
            else
            {
                cout<<"读取错误"<<endl;
                break;
            }
        }
    }
    bool Start()
    {
        for(int i=0;i<process_num;i++)
        {
            int pipefd[2]={0};
            int n = pipe(pipefd);
            if(n<0)
            {
                return false;
            }
            pid_t subid = fork();
            if(subid<0)
            {
                return false;
            }
            else if(subid==0)
            {
                close(pipefd[1]);
                Work(pipefd[0]);//子进程只读
                close(pipefd[0]);
                exit(0);
            }
            else
            {
                close(pipefd[0]);
                cm.Insert(pipefd[1],subid);//父进程只写
            }
        }
        return true;
    }
    void Debug()
    {
        cm.Printchannel();//打印所有的管道信息
    }
    void Run()
    {
        int taskcode = tm.Code();//生成随机数
        auto &c=cm.Select();//轮询选择一个管道
        cout<<"选择了一个子进程"<<c.Name()<<endl;
        c.Send(taskcode);//发送一个任务码
        cout<<"发送了一个任务码:"<<taskcode<<endl;
    }
    void Stop()
    {
        cm.Stopchannels();
        cm.Waitchannels();
    }   
    ~processpool()
    {}
    private:
    channelmanage cm;
    int process_num;
    taskmanage tm;
};